﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DatabaseExtension.QueryBuilder
{
    public class QueryBuilder : IQueryBuilder
    {
        public static Char ObjectOperator = '.';
        public static Char ColumnSeparator = ',';
        public static readonly String[] QueryKeyWords = new String[7] { "SELECT", "FROM", "WHERE", "GROUP BY", "ORDER BY", "AND", "OR" };
        public String QuotePrefix;
        public String QuoteSuffix;
        public String Query
        {
            get 
            {
                String selectColumns = null;
                if(this.DistinctColumns.Count>0)
                {
                    selectColumns = String.Join(String.Concat(this.QuotePrefix, ColumnSeparator, this.QuoteSuffix), this.DistinctColumns);
                }
                if(this.SelectColumns.Count>0)
                {
                    //selectColumns = String.
                }
                //String result = String.Concat(this.QueryKeyWords[0], selectColumns, this.QueryKeyWords[1]


                return String.Empty;//result;
            }
        }
        protected IQueryBuilder ParentSelect;
        /// <summary>
        /// Containing the limitation value for String Builder.
        /// </summary>
        protected Int64 _Limitation;
        /// <summary>
        /// Containing the Distinct columns, if it set, select Columns are unavailable.
        /// </summary>
        protected List<String> DistinctColumns;
        protected List<String> SelectColumns;
        protected List<String> WhereColumns;
        protected List<String> GroupByColumns;
        protected List<String> OrderByColumns;
        protected List<IQueryBuilder> UnionObjects;
        protected List<IQueryBuilder> UnionAllObjects;
        protected String _From;

        public QueryBuilder()
        {
            this.QuotePrefix = "[";
            this.QuoteSuffix = "]";
            this._Limitation = -1;
            this.DistinctColumns = new List<String>();
            this.SelectColumns = new List<String>();
            this.WhereColumns = new List<String>();
            this.GroupByColumns = new List<String>();
            this.OrderByColumns = new List<String>();
            this.UnionObjects = new List<IQueryBuilder>();
            this.UnionAllObjects = new List<IQueryBuilder>();
        }


        public IQueryBuilder Top(Int64 limitation)
        {
            this._Limitation = limitation;
            return this;
        }

        public IQueryBuilder Distinct(String def)
        {
            if (this.SelectColumns.Count > 0)
                throw new ArgumentException("Could not add new column(s) to the statement, select columns already defined.");

            this.DistinctColumns.AddRange(def.Split(QueryBuilder.ColumnSeparator));
            return this;
        }

        public IQueryBuilder Select(String def)
        {
            if (this.DistinctColumns.Count > 0)
                throw new ArgumentException("Could not add new column(s) to the statement, distinct columns already defined.");

            this.SelectColumns.AddRange(def.Split(QueryBuilder.ColumnSeparator));
            return this;
        }

        public IQueryBuilder From(String table)
        {
            return this.From(null, table);
        }

        public IQueryBuilder From(String schema, String table)
        {
            return this.From(null, schema, table);
        }

        public IQueryBuilder From(String database, String schema, String table)
        {
            this._From = String.Concat(this.QuotePrefix, database, this.QuoteSuffix, QueryBuilder.ObjectOperator, this.QuotePrefix, schema, this.QuoteSuffix, QueryBuilder.ObjectOperator, this.QuotePrefix, table, this.QuoteSuffix);
            return this;
        }

        public IQueryBuilder Where(String def)
        {
            this.WhereColumns.Add(def);
            return this;
        }

        public IQueryBuilder GroupBy(string def)
        {
            this.GroupByColumns.AddRange(def.Split(QueryBuilder.ColumnSeparator));
            return this;
        }

        public IQueryBuilder OrderBy(string def)
        {
            this.OrderByColumns.AddRange(def.Split(QueryBuilder.ColumnSeparator));
            return this;
        }

        public IQueryBuilder BeginUnion()
        {
            var union = new QueryBuilder();
            this.UnionObjects.Add(union);
            union.ParentSelect = this;
            return union;
        }
        
        public IQueryBuilder EndUnion()
        {
            if (this.ParentSelect != null)
                return this.ParentSelect;
            else
                throw new ArgumentException("Could not end Union, because no parent object found.");
        }

        public IQueryBuilder UnionAll()
        {
            var union = new QueryBuilder();
            this.UnionObjects.Add(union);
            union.ParentSelect = this;
            return union;
        }

        public IQueryBuilder EndUnionAll()
        {
            if (this.ParentSelect != null)
                return this.ParentSelect;
            else
                throw new ArgumentException("Could not end Union, because no parent object found.");
        }
    }
}
